home *** CD-ROM | disk | FTP | other *** search
/ PC World 2006 February / PCWorld_2006-02_cd.bin / software / vyzkuste / triky / triky.exe / httrack-3.33.exe / {app} / src / htsserver.c < prev    next >
C/C++ Source or Header  |  2005-02-05  |  56KB  |  1,709 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: Mini-server                                            */
  34. /* Author: Xavier Roche                                         */
  35. /* ------------------------------------------------------------ */
  36.  
  37.  
  38. /* specific definitions */
  39. /* specific definitions */
  40.  
  41. /* Bypass internal definition protection */
  42. #define HTS_INTERNAL_BYTECODE
  43.   #include "htsbase.h"
  44. #undef HTS_INTERNAL_BYTECODE
  45.  
  46. #include "htsnet.h"
  47. #include "htslib.h"
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include <time.h>
  52. #include <fcntl.h>
  53. #if HTS_WIN
  54. #else
  55. #include <arpa/inet.h>
  56. #endif
  57. #ifndef _WIN32
  58. #include <signal.h>
  59. #endif
  60. /* END specific definitions */
  61.  
  62. /* dΘfinitions globales */
  63. #include "htsglobal.h"
  64.  
  65. /* htslib */
  66. /*#include "htslib.h"*/
  67.  
  68. /* HTTrack Website Copier Library */
  69. #include "httrack-library.h"
  70.  
  71. /* Language files */
  72.  
  73. /* Bypass internal definition protection */
  74. #define HTS_INTERNAL_BYTECODE
  75.   #include "htsinthash.h"
  76. #undef HTS_INTERNAL_BYTECODE
  77.  
  78. int NewLangStrSz=1024;
  79. inthash NewLangStr=NULL;
  80. int NewLangStrKeysSz=1024;
  81. inthash NewLangStrKeys=NULL;
  82. int NewLangListSz=1024;
  83. inthash NewLangList=NULL;
  84. /* Language files */
  85.  
  86. #include "htsserver.h"
  87.  
  88. char* gethomedir(void);
  89. int commandRunning = 0;
  90. int commandEndRequested = 0;
  91. int commandEnd = 0;
  92. int commandReturn = 0;
  93. char* commandReturnMsg = NULL;
  94. char* commandReturnCmdl = NULL;
  95. int commandReturnSet = 0;
  96.  
  97. /* Extern */
  98. extern void webhttrack_main(char* cmd);
  99. extern void webhttrack_lock(int lock);
  100.  
  101. static int is_image(char* file) {
  102.   return ( (strstr(file, ".gif") != NULL) );
  103. }
  104. static int is_text(char* file) {
  105.   return ( (strstr(file, ".txt") != NULL) );
  106. }
  107. static int is_html(char* file) {
  108.   return ( (strstr(file, ".htm") != NULL) );
  109. }
  110.  
  111. static void sig_brpipe( int code ) {
  112.   /* ignore */
  113. }
  114.  
  115. static int check_readinput_t(T_SOC soc, int timeout);
  116. static int recv_bl(T_SOC soc, void* buffer, size_t len, int timeout);
  117. static int linputsoc(T_SOC soc, char* s, int max);
  118. static int check_readinput(htsblk* r);
  119. static int linputsoc_t(T_SOC soc, char* s, int max, int timeout);
  120.  
  121.  
  122. static int linput(FILE* fp,char* s,int max);
  123.  
  124.  
  125. // URL Link catcher
  126.  
  127. // 0- Init the URL catcher with standard port
  128.  
  129. // smallserver_init(&port,&return_host);
  130. T_SOC smallserver_init_std(int* port_prox,char* adr_prox) {
  131.   T_SOC soc;
  132.   int try_to_listen_to[]={8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,
  133.                           32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,
  134.                           42000,42001,42002,42003,42004,42005,42006,42007,42008,42009,
  135.                           0,-1};
  136.   int i=0;
  137.   do {
  138.     soc=smallserver_init(&try_to_listen_to[i],adr_prox);
  139.     *port_prox=try_to_listen_to[i];
  140.     i++;
  141.   } while( (soc == INVALID_SOCKET) && (try_to_listen_to[i]>=0));
  142.   return soc;
  143. }
  144.  
  145.  
  146. // 1- Init the URL catcher
  147.  
  148. // smallserver_init(&port,&return_host);
  149. T_SOC smallserver_init(int* port,char* adr) {
  150.   T_SOC soc = INVALID_SOCKET;
  151.   char h_loc[256+2];
  152.   
  153.   commandRunning = 
  154.     commandEnd = 
  155.     commandReturn = 
  156.     commandReturnSet =
  157.     commandEndRequested = 0;
  158.   if (commandReturnMsg)
  159.     free(commandReturnMsg);
  160.   commandReturnMsg = NULL;
  161.   if (commandReturnCmdl)
  162.     free(commandReturnCmdl);
  163.   commandReturnCmdl = NULL;
  164.  
  165.   if (gethostname(h_loc,256)==0) {    // host name
  166.     SOCaddr server;
  167.     int server_size=sizeof(server);
  168.     /*t_hostent* hp_loc;
  169.     t_fullhostent buffer;*/
  170.  
  171.     // effacer structure
  172.     memset(&server, 0, sizeof(server));
  173.     
  174.     /*if ( (hp_loc=vxgethostbyname(h_loc, &buffer)) )*/ {  // notre host      
  175.  
  176.       // copie adresse
  177.       // NO (bind all)
  178.       // SOCaddr_copyaddr(server, server_size, hp_loc->h_addr_list[0], hp_loc->h_length);
  179.  
  180.       SOCaddr_initany(server, server_size); 
  181.       if ( (soc=socket(SOCaddr_sinfamily(server), SOCK_STREAM, 0)) != INVALID_SOCKET) {
  182.         SOCaddr_initport(server, *port);
  183.         if ( bind(soc,(struct sockaddr*) &server, server_size) == 0 ) {
  184.           /*int len;
  185.           SOCaddr server2;
  186.           len=sizeof(server2);*/
  187.           // effacer structure
  188.           /*memset(&server2, 0, sizeof(server2));
  189.           if (getsockname(soc,(struct sockaddr*) &server2,&len) == 0) {
  190.             *port=ntohs(SOCaddr_sinport(server));  // rΘcupΘrer port*/
  191.             if (listen(soc,10)>=0) {    // au pif le 10
  192.               // SOCaddr_inetntoa(adr, 128, server2, len);
  193.               strcpy(adr, h_loc);
  194.             } else {
  195. #ifdef _WIN32
  196.               closesocket(soc);
  197. #else
  198.               close(soc);
  199. #endif
  200.               soc=INVALID_SOCKET;
  201.             }
  202.             
  203.             
  204.           /*} else {
  205. #ifdef _WIN32
  206.             closesocket(soc);
  207. #else
  208.             close(soc);
  209. #endif
  210.             soc=INVALID_SOCKET;
  211.           }*/
  212.           
  213.           
  214.         } else {
  215. #ifdef _WIN32
  216.           closesocket(soc);
  217. #else
  218.           close(soc);
  219. #endif
  220.           soc=INVALID_SOCKET;
  221.         }
  222.       }
  223.     }
  224.   }
  225.   return soc;
  226. }
  227.  
  228. // 2 - Wait for URL
  229.  
  230.  
  231. // check if data is available
  232.  
  233. // smallserver
  234. // returns 0 if error
  235. // url: buffer where URL must be stored - or ip:port in case of failure
  236. // data: 32Kb
  237.  
  238. typedef struct {
  239.   char* name;
  240.   int value;
  241. } initIntElt;
  242. typedef struct {
  243.   char* name;
  244.   char* value;
  245. } initStrElt;
  246.  
  247. #define SET_ERROR(err) do { \
  248.   inthash_write(NewLangList, "error", (unsigned long int)strdup(err)); \
  249.   error_redirect = "/server/error.html"; \
  250. } while(0)
  251.  
  252. int smallserver(T_SOC soc,char* url,char* method,char* data, char* path) {
  253.   int timeout=30;
  254.   int retour=0;
  255.   int willexit=0;
  256.   int buffer_size = 32768;
  257.   char* buffer = (char*)malloc(buffer_size);
  258.   String headers = STRING_EMPTY;
  259.   String output = STRING_EMPTY;
  260.   String tmpbuff = STRING_EMPTY;
  261.   String tmpbuff2 = STRING_EMPTY;
  262.   String fspath = STRING_EMPTY;
  263.  
  264.   /* Load strings */
  265.   htslang_init();
  266.   if (!htslang_load(NULL, path)) {
  267.     fprintf(stderr, "unable to find lang.def and/or lang/ strings in %s\n", path);
  268.     return 0;
  269.   }
  270.   LANG_T(path, 0);
  271.  
  272.   /* Init various values */
  273.   {
  274.     char pth[1024];
  275.     char* initOn[] = { "parseall", "Cache", "ka", 
  276.       "cookies", "parsejava", "testall", "updhack", "urlhack", "index", NULL };
  277.     initIntElt initInt[] = {
  278.       { "filter", 4 },
  279.       { "travel", 2 },
  280.       { "travel2", 1 },
  281.       { "travel3", 1 },
  282.       /* */
  283.       { "connexion", 4 },
  284.       /* */
  285.       { "maxrate", 25000 },
  286.       /* */
  287.       { "build", 1 },
  288.       /* */
  289.       { "checktype", 2},
  290.       { "robots", 3 },
  291.  
  292.       { NULL, 0 } 
  293.     };
  294.     initStrElt initStr[] = {
  295.       { "user", "Mozilla/4.5 (compatible; HTTrack 3.0x; Windows 98)" },
  296.       { "footer", "<!-- Mirrored from %s%s by HTTrack Website Copier/3.x [XR&CO'2005], %s -->" },
  297.       { "url2", "+*.png +*.gif +*.jpg +*.css +*.js -ad.doubleclick.net/*" },
  298.       { NULL, NULL }
  299.     };
  300.     int i = 0;
  301.     for(i = 0 ; initInt[i].name ; i++) {
  302.       char tmp[32];
  303.       sprintf(tmp, "%d", initInt[i].value);
  304.       inthash_write(NewLangList, initInt[i].name, (unsigned long int)strdup(tmp));
  305.     }
  306.     for(i = 0 ; initOn[i] ; i++) {
  307.       inthash_write(NewLangList, initOn[i], (unsigned long int)strdup("1"));  /* "on" */
  308.     }
  309.     for(i = 0 ; initStr[i].name ; i++) {
  310.       inthash_write(NewLangList, initStr[i].name, (unsigned long int)strdup(initStr[i].value));
  311.     }
  312.     strcpybuff(pth, gethomedir());
  313.     strcatbuff(pth, "/websites");
  314.     inthash_write(NewLangList, "path", (unsigned long int)strdup(pth));
  315.   }
  316.  
  317.   /* Lock */
  318.   webhttrack_lock(1);
  319.  
  320.   // connexion (accept)
  321.   while(!willexit && buffer != NULL && soc != INVALID_SOCKET) {
  322.     char line1[1024];
  323.     char line[8192];
  324.     char line2[1024];
  325.     T_SOC soc_c;
  326.     struct sockaddr dummyaddr;
  327.     int dummylen = sizeof(struct sockaddr);
  328.     LLint length = 0;
  329.     char* error_redirect = NULL;
  330.  
  331.     line[0] = '\0';
  332.     buffer[0] = '\0';
  333.     StringClear(headers);
  334.     StringClear(output);
  335.     StringClear(tmpbuff);
  336.     StringClear(tmpbuff2);
  337.     StringClear(fspath);
  338.     StringStrcat(headers, "");
  339.     StringStrcat(output, "");
  340.     StringStrcat(tmpbuff, "");
  341.     StringStrcat(tmpbuff2, "");
  342.     StringStrcat(fspath, "");
  343.     memset(&dummyaddr, 0, sizeof(dummyaddr));
  344.  
  345.     /* UnLock */
  346.     webhttrack_lock(0);
  347.  
  348.     /* sigpipe */
  349. #ifndef _WIN32
  350.     signal( SIGPIPE , sig_brpipe );
  351. #endif
  352.  
  353.     /* Accept */
  354.     while ( (soc_c = accept(soc, &dummyaddr, &dummylen)) == INVALID_SOCKET);
  355.  
  356.     /* Lock */
  357.     webhttrack_lock(1);
  358.  
  359.     if(linputsoc_t(soc_c, line1, sizeof(line1) - 2, timeout) > 0) {
  360.       int meth = 0;
  361.       if (strfield(line1, "get ")) {
  362.         meth = 1;
  363.       } else if (strfield(line1, "post ")) {
  364.         meth = 2;
  365.       } else if (strfield(line1, "head ")) {   /* yes, we can do that */
  366.         meth = 10;
  367.       } else {
  368. #ifdef _DEBUG
  369.         // assert(FALSE);
  370. #endif
  371.       }
  372.       if (meth) {
  373.         /* Flush headers */
  374.         length = buffer_size - 2;
  375.         while(linputsoc_t(soc_c, line, sizeof(line) - 2, timeout) > 0) {
  376.           int p;
  377.           if ((p=strfield(line,"Content-length:"))!=0) {
  378.             sscanf(line+p, LLintP, &(length));
  379.           }
  380.           else if ((p=strfield(line,"Accept-language:"))!=0) {
  381.             char tmp[32];
  382.             char* s = line + p;
  383.             /*int l;*/
  384.             while(*s == ' ') s++;
  385.             tmp[0] = '\0';
  386.             strncatbuff(tmp, s, 2);
  387.             /*l = LANG_SEARCH(path, tmp);*/
  388.           }
  389.         }
  390.         if (meth == 2) {
  391.           int sz = 0;
  392.           if (length > buffer_size - 2) {
  393.             length = buffer_size - 2;
  394.           }
  395.           if (length > 0 && (sz=recv_bl(soc_c, buffer, (int)length, timeout)) < 0) {
  396.             meth = 0;
  397.           } else {
  398.             buffer[sz] = '\0';
  399.           }
  400.         }
  401.       }
  402.  
  403.       /* Generated variables */
  404.       if (commandEnd && !commandReturnSet) {
  405.         commandReturnSet = 1;
  406.         if (commandReturn) {
  407.           char tmp[32];
  408.           sprintf(tmp, "%d", commandReturn);
  409.           inthash_write(NewLangList, "commandReturn", (unsigned long int)strdup(tmp));
  410.           inthash_write(NewLangList, "commandReturnMsg", (unsigned long int)commandReturnMsg);
  411.           inthash_write(NewLangList, "commandReturnCmdl", (unsigned long int)commandReturnCmdl);
  412.         } else {
  413.           inthash_write(NewLangList, "commandReturn", (unsigned long int)NULL);
  414.           inthash_write(NewLangList, "commandReturnMsg", (unsigned long int)NULL);
  415.           inthash_write(NewLangList, "commandReturnCmdl", (unsigned long int)NULL);
  416.         }
  417.       }
  418.  
  419.       /* SID check */
  420.       {
  421.         unsigned long int adr = 0;
  422.         if (inthash_readptr(NewLangList, "_sid", (long int *)&adr)) {
  423.           if (inthash_write(NewLangList, "sid", (unsigned long int)strdup((char*)adr))) {
  424.           }
  425.         }
  426.       }
  427.  
  428.       /* check variables */
  429.       if (meth && buffer[0]) {
  430.         char* s = buffer;
  431.         char *e, *f;
  432.         strcatbuff(buffer, "&");
  433.         while( s && (e = strchr(s, '=')) && (f = strchr(s, '&')) ) {
  434.           char* ua;
  435.           int len;
  436.           String sua = STRING_EMPTY;
  437.           *e = *f = '\0';
  438.           ua = e + 1;
  439.           if (strfield2(ua, "on"))  /* hack : "on" == 1 */
  440.             ua = "1";
  441.           len = strlen(ua);
  442.           unescapehttp(ua, &sua);
  443.           inthash_write(NewLangList, s, (unsigned long int)StringAcquire(&sua));
  444.           s = f + 1;
  445.         }
  446.       }
  447.  
  448.  
  449.       /* Error check */
  450.       {
  451.         unsigned long int adr = 0;
  452.         unsigned long int adr2 = 0;
  453.         if (inthash_readptr(NewLangList, "sid", (long int *)&adr)) {
  454.           if (inthash_readptr(NewLangList, "_sid", (long int *)&adr2)) {
  455.             if (strcmp((char*)adr, (char*)adr2) != 0) {
  456.               meth = 0;
  457.             }
  458.           }
  459.         }
  460.       }
  461.  
  462.       /* Check variables (internal) */
  463.       if (meth) {
  464.         int doLoad=0;
  465.         unsigned long int adr = 0;
  466.         if (inthash_readptr(NewLangList, "lang", (long int *)&adr)) {
  467.           int n = 0;
  468.           if (sscanf((char*)adr, "%d", &n) == 1 && n > 0 && n - 1 != LANG_T(path, -1)) {
  469.             LANG_T(path, n - 1);
  470.             /* make a backup, because the GUI will override it */
  471.             inthash_write(NewLangList, "lang_", (unsigned long int)strdup((char*)adr));
  472.           }
  473.         }
  474.  
  475.         /* Load existing project settings */
  476.         if (inthash_readptr(NewLangList, "loadprojname", (long int *)&adr)) {
  477.           char* pname = (char*) adr;
  478.           if (*pname) {
  479.             inthash_write(NewLangList, "projname", (unsigned long int)strdup(pname));
  480.           }
  481.           inthash_write(NewLangList, "loadprojname", (unsigned long int)NULL);
  482.           doLoad=1;
  483.         }
  484.         else if (inthash_readptr(NewLangList, "loadprojcateg", (long int *)&adr)) {
  485.           char* pname = (char*) adr;
  486.           if (*pname) {
  487.             inthash_write(NewLangList, "projcateg", (unsigned long int)strdup(pname));
  488.           }
  489.           inthash_write(NewLangList, "loadprojcateg", (unsigned long int)NULL);
  490.         }
  491.         
  492.         /* intial configuration */
  493.         {
  494.           if (!inthash_read(NewLangList, "conf_file_loaded", NULL)) {
  495.             inthash_write(NewLangList, "conf_file_loaded", (unsigned long int)strdup("true"));
  496.             doLoad = 2;
  497.           }
  498.         }
  499.         
  500.         /* path : <path>/<project> */
  501.         if (!commandRunning) {
  502.           unsigned long int adrw = 0, adrpath = 0, adrprojname = 0;
  503.           if (inthash_readptr(NewLangList, "path", (long int *)&adrpath)
  504.             && inthash_readptr(NewLangList, "projname", (long int *)&adrprojname)) {
  505.             StringClear(fspath);
  506.             StringStrcat(fspath, (char*)adrpath);
  507.             StringStrcat(fspath, "/");
  508.             StringStrcat(fspath, (char*)adrprojname);
  509.           }
  510.         }
  511.         
  512.         /* Load existing project settings */
  513.         if (doLoad) {
  514.           FILE* fp;
  515.           if (doLoad == 1) {
  516.             StringStrcat(fspath, "/hts-cache/winprofile.ini");
  517.           } else if (doLoad == 2) {
  518.             StringStrcpy(fspath, gethomedir());
  519. #ifdef _WIN32
  520.             StringStrcat(fspath, "/httrack.ini");
  521. #else
  522.             StringStrcat(fspath, "/.httrack.ini");
  523. #endif
  524.           }
  525.           fp = fopen(StringBuff(fspath), "rb");
  526.           if (fp) {
  527.             /* Read file */
  528.             while(!feof(fp)) {
  529.               char* str = line;
  530.               char* pos;
  531.               if (!linput(fp, line, sizeof(line) - 2)) {
  532.                 *str = '\0';
  533.               }
  534.               pos=strchr(line, '=');
  535.               if (pos) {
  536.                 String escline = STRING_EMPTY;
  537.                 *pos++='\0';
  538.                 if (pos[0] == '0' && pos[1] == '\0')
  539.                   *pos = '\0';   /* 0 => empty */
  540.                 unescapeini(pos, &escline);
  541.                 inthash_write(NewLangList, line, (unsigned long int)StringAcquire(&escline));
  542.               }
  543.             }
  544.             
  545.             fclose(fp);
  546.           }
  547.         }
  548.         
  549.       }
  550.  
  551.       /* Execute command */
  552.       {
  553.         unsigned long int adr = 0;
  554.         int p = 0;
  555.         if (inthash_readptr(NewLangList, "command", (long int *)&adr)) {
  556.           if (strcmp((char*)adr, "cancel") == 0) {
  557.             if (commandRunning) {
  558.               if (!commandEndRequested) {
  559.                 commandEndRequested=1;
  560.                 hts_request_stop(0);
  561.               } else {
  562.                 hts_request_stop(1);   /* note: the force flag does not have anyeffect yet */
  563.                 commandEndRequested=2; /* will break the loop() callback */
  564.               }
  565.             }
  566.           } else if ((p=strfield((char*)adr, "cancel-file="))) {
  567.             if (commandRunning) {
  568.               hts_cancel_file((char*)adr + p);
  569.             }
  570.           } else if (strcmp((char*)adr, "cancel-parsing") == 0) {
  571.             if (commandRunning) {
  572.               hts_cancel_parsing();
  573.             }
  574.           } else if ((p=strfield((char*)adr, "pause="))) {
  575.             if (commandRunning) {
  576.               hts_setpause(1);
  577.             }
  578.           } else if ((p=strfield((char*)adr, "unpause"))) {
  579.             if (commandRunning) {
  580.               hts_setpause(0);
  581.             }
  582.           } else if (strcmp((char*)adr, "abort") == 0) {
  583.             if (commandRunning) {
  584.               hts_request_stop(1);
  585.               commandEndRequested=2; /* will break the loop() callback */
  586.             }
  587.           } else if ((p=strfield((char*)adr, "add-url="))) {
  588.             if (commandRunning) {
  589.               char* ptraddr[2];
  590.               ptraddr[0] = (char*)adr + p;
  591.               ptraddr[1] = NULL;
  592.               hts_addurl(ptraddr);
  593.             }
  594.           } else if ((p=strfield((char*)adr, "httrack"))) {
  595.             if (!commandRunning) {
  596.               unsigned long int adrcd = 0;
  597.               if (inthash_readptr(NewLangList, "command_do", (long int *)&adrcd)) {
  598.                 unsigned long int adrw = 0, adrpath = 0, adrprojname = 0;
  599.                 if (inthash_readptr(NewLangList, "winprofile", (long int *)&adrw)) {
  600.  
  601.                   /* User general profile */
  602.                   unsigned long int adruserprofile = 0;
  603.                   if (inthash_readptr(NewLangList, "userprofile", (long int *)&adruserprofile)
  604.                     && adruserprofile != 0) {
  605.                     int count = (int) strlen((char*)adruserprofile);
  606.                     if (count > 0) {
  607.                       FILE* fp;
  608.                       StringClear(tmpbuff);
  609.                       StringStrcpy(tmpbuff, gethomedir());
  610. #ifdef _WIN32
  611.                       StringStrcat(tmpbuff, "/httrack.ini");
  612. #else
  613.                       StringStrcat(tmpbuff, "/.httrack.ini");
  614. #endif
  615.                       fp = fopen(StringBuff(tmpbuff), "wb");
  616.                       if (fp != NULL) {
  617.                         (void)((int)fwrite((void*)adruserprofile, 1, count, fp));
  618.                         fclose(fp);
  619.                       }
  620.                     }
  621.                   }
  622.                   
  623.                   /* Profile */
  624.                   StringClear(tmpbuff);
  625.                   StringStrcat(tmpbuff, StringBuff(fspath));
  626.                   StringStrcat(tmpbuff, "/hts-cache/");
  627.                   
  628.                   /* Create minimal directory structure */
  629.                   if (!structcheck(StringBuff(tmpbuff))) {
  630.                     FILE* fp;
  631.                     StringStrcat(tmpbuff, "winprofile.ini");
  632.                     fp = fopen(StringBuff(tmpbuff), "wb");
  633.                     if (fp != NULL) {
  634.                       int count = (int) strlen((char*)adrw);
  635.                       if ((int)fwrite((void*)adrw, 1, count, fp) == count) {
  636.                         
  637.                       /* Wipe the doit.log file, useless here (all options are replicated) and
  638.                       even a bit annoying (duplicate/ghost options)
  639.                       The behaviour is exactly the same as in WinHTTrack
  640.                         */
  641.                         StringClear(tmpbuff);
  642.                         StringStrcat(tmpbuff, StringBuff(fspath));
  643.                         StringStrcat(tmpbuff, "/hts-cache/doit.log");
  644.                         remove(StringBuff(tmpbuff));
  645.                         
  646.                         /*
  647.                         RUN THE SERVER
  648.                         */
  649.                         if (strcmp((char*)adrcd, "start") == 0) {
  650.                           webhttrack_main((char*)adr + p);
  651.                         } else {
  652.                           commandRunning = 0;
  653.                           commandEnd = 1;
  654.                         }
  655.                       } else {
  656.                         char tmp[1024];
  657.                         sprintf(tmp, "Unable to write %d bytes in the the init file %s", count, StringBuff(fspath));
  658.                         SET_ERROR(tmp);
  659.                       }
  660.                       fclose(fp);
  661.                     } else {
  662.                       char tmp[1024];
  663.                       sprintf(tmp, "Unable to create the init file %s", StringBuff(fspath));
  664.                       SET_ERROR(tmp);
  665.                     }
  666.                   } else {
  667.                     char tmp[1024];
  668.                     sprintf(tmp, "Unable to create the directory structure in %s", StringBuff(fspath));
  669.                     SET_ERROR(tmp);
  670.                   }
  671.                   
  672.                 } else {
  673.                   SET_ERROR("Internal server error: unable to fetch project name or path");
  674.                 }
  675.               }
  676.             }
  677.           } else if (strcmp((char*)adr, "quit") == 0) {
  678.             willexit=1;
  679.           }
  680.           inthash_write(NewLangList, "command", (unsigned long int)NULL);
  681.         }
  682.       }
  683.  
  684.       /* Response */
  685.       if (meth) {
  686.         int virtualpath = 0;
  687.         char* pos;
  688.         char* url = strchr(line1, ' ');
  689.         if (url && *++url == '/' && (pos = strchr(url, ' ')) && !(*pos = '\0') ) {
  690.           char fsfile[1024];
  691.           char* file;
  692.           FILE* fp;
  693.           char* qpos;
  694.  
  695.           /* get the URL */
  696.           if (error_redirect == NULL) {
  697.             if ( (qpos = strchr(url, '?')) ) {
  698.               *qpos = '\0';
  699.             }
  700.             fsfile[0] = '\0';
  701.             if (strcmp(url, "/") == 0) {
  702.               file = "/server/index.html";
  703.               meth = 2;
  704.             } else {
  705.               file = url;
  706.             }
  707.           } else {
  708.             file = error_redirect;
  709.             meth = 2;
  710.           }
  711.           
  712.           if (strncmp(file, "/website/", 9) == 0) {
  713.             virtualpath = 1;
  714.           }
  715.  
  716.           if (commandRunning) {
  717.             if (!is_image(file)) {
  718.               file = "/server/refresh.html";
  719.             }
  720.           } else if (commandEnd && !virtualpath && !willexit) {
  721.             if (!is_image(file)) {
  722.               file = "/server/finished.html";
  723.             }
  724.           }
  725.           
  726.           if (strlen(path) + strlen(file) + 32 < sizeof(fsfile)) {
  727.             if (strncmp(file, "/website/", 9) != 0) {
  728.               sprintf(fsfile, "%shtml%s", path, file);
  729.             } else {
  730.               unsigned long int adr = 0;
  731.               if (inthash_readptr(NewLangList, "projpath", (long int *)&adr)) {
  732.                 sprintf(fsfile, "%s%s", (char*)adr, file + 9);
  733.               }
  734.             }
  735.           }
  736.           
  737.           if (fsfile[0] && strstr(file, "..") == NULL && (fp = fopen(fsfile, "rb"))) {
  738.             char ok[] = "HTTP/1.0 200 OK\r\n"
  739.               "Connection: close\r\n"
  740.               "Server: httrack-small-server\r\n"
  741.               "Content-type: text/html\r\n"
  742.               "Cache-Control: no-cache, must-revalidate, private\r\n"
  743.               "Pragma: no-cache\r\n"
  744.               ;
  745.             char ok_img[] = "HTTP/1.0 200 OK\r\n"
  746.               "Connection: close\r\n"
  747.               "Server: httrack small server\r\n"
  748.               "Content-type: image/gif\r\n"
  749.               ;
  750.             char ok_text[] = "HTTP/1.0 200 OK\r\n"
  751.               "Connection: close\r\n"
  752.               "Server: httrack small server\r\n"
  753.               "Content-type: text/plain\r\n"
  754.               ;
  755.  
  756.             /* register current page */
  757.             inthash_write(NewLangList, "thisfile", (unsigned long int)strdup(file));
  758.  
  759.             /* Force GET for the last request */
  760.             if (meth == 2 && willexit) {
  761.               meth = 1;
  762.             }
  763.  
  764.             /* posted data are redirected to get protocol */
  765.             if (meth == 2) {
  766.               char redir[] = "HTTP/1.0 302 Redirect\r\n"
  767.                 "Connection: close\r\n"
  768.                 "Server: httrack-small-server\r\n";
  769.               unsigned long int adr = 0;
  770.               char* newfile = file;
  771.               if (inthash_readptr(NewLangList, "redirect", (long int *)&adr) && adr != 0) {
  772.                 char* newadr = (char*)adr;
  773.                 if (*newadr) {
  774.                   newfile = newadr;
  775.                 }
  776.               }
  777.               StringMemcat(headers, redir, strlen(redir));
  778.               {
  779.                 char tmp[256];
  780.                 if (strlen(file) < sizeof(tmp) - 32) {
  781.                   sprintf(tmp, "Location: %s\r\n", newfile);
  782.                   StringMemcat(headers, tmp, strlen(tmp));
  783.                 }
  784.               }
  785.               inthash_write(NewLangList, "redirect", (unsigned long int)NULL);
  786.             }
  787.             else if (is_html(file)) {
  788.               int outputmode = 0;
  789.               StringMemcat(headers, ok, sizeof(ok) - 1);
  790.               while(!feof(fp)) {
  791.                 char* str = line;
  792.                 int prevlen = StringLength(output);
  793.                 int nocr = 0;
  794.                 if (!linput(fp, line, sizeof(line) - 2)) {
  795.                   *str = '\0';
  796.                 }
  797.                 if (*str && str[strlen(str) - 1] == '\\') {
  798.                   nocr = 1;
  799.                   str[strlen(str) - 1] = '\0';
  800.                 }
  801.                 while(*str) {
  802.                   char* pos;
  803.                   int n;
  804.                   if (*str == '$' && *++str == '{' && (pos = strchr(++str, '}')) && (n = (pos - str) ) && n < 1024 ) {
  805.                     char name_[1024 + 2];
  806.                     char* name = name_;
  807.                     char* langstr = NULL;
  808.                     int p;
  809.                     int format = 0;
  810.                     int listDefault = 0;
  811.                     name[0] = '\0';
  812.                     strncatbuff(name, str, n);
  813.                     if (strncmp(name, "/*", 2) == 0) {
  814.                       /* comments */
  815.                     }
  816.                     else if (( p = strfield(name, "html:"))) {
  817.                       name += p;
  818.                       format = 1;
  819.                     }
  820.                     else if (( p = strfield(name, "list:"))) {
  821.                       name += p;
  822.                       format = 2;
  823.                     }
  824.                     else if (( p = strfield(name, "liststr:"))) {
  825.                       name += p;
  826.                       format = -2;
  827.                     }
  828.                     else if (( p = strfield(name, "file-exists:"))) {
  829.                       char* pos2;
  830.                       name += p;
  831.                       format = 0;
  832.                       pos2 = strchr(name, ':');
  833.                       langstr = "";
  834.                       if (pos2 != NULL) {
  835.                         *pos2 = '\0';
  836.                         if (strstr(name, "..") == NULL) {
  837.                           if (fexist(fconcat(path, name))) {
  838.                             langstr = pos2 + 1;
  839.                           }
  840.                         }
  841.                       }
  842.                     }
  843.                     else if (( p = strfield(name, "do:"))) {
  844.                       char* pos2;
  845.                       name += p;
  846.                       format = 1;
  847.                       pos2 = strchr(name, ':');
  848.                       langstr = "";
  849.                       if (pos2 != NULL) {
  850.                         *pos2 = '\0';
  851.                         pos2++;
  852.                       } else {
  853.                         pos2="";
  854.                       }
  855.                       if (strcmp(name, "output-mode") == 0) {
  856.                         if (strcmp(pos2, "html") == 0) {
  857.                           outputmode = 1;
  858.                         } else if (strcmp(pos2, "inifile") == 0) {
  859.                           outputmode = 2;                         
  860.                         } else if (strcmp(pos2, "html-urlescaped") == 0) {
  861.                           outputmode = 3;                         
  862.                         } else {
  863.                           outputmode = 0;
  864.                         }
  865.                       } else if (strcmp(name, "if-file-exists") == 0) {
  866.                         if (strstr(pos2, "..") == NULL) {
  867.                           if (!fexist(fconcat(path, pos2))) {
  868.                             outputmode = -1;
  869.                           }
  870.                         }
  871.                       } else if (strcmp(name, "if-project-file-exists") == 0) {
  872.                         if (strstr(pos2, "..") == NULL) {
  873.                           if (!fexist(fconcat(StringBuff(fspath), pos2))) {
  874.                             outputmode = -1;
  875.                           }
  876.                         }
  877.                       } else if (strcmp(name, "if-file-do-not-exists") == 0) {
  878.                         if (strstr(pos2, "..") == NULL) {
  879.                           if (fexist(fconcat(path, pos2))) {
  880.                             outputmode = -1;
  881.                           }
  882.                         }
  883.                       } else if (strcmp(name, "if-not-empty") == 0) {
  884.                         unsigned long int adr = 0;
  885.                         if (!inthash_readptr(NewLangList, pos2, (long int *)&adr) || *((char*)adr) == 0 ) {
  886.                           outputmode = -1;
  887.                         }
  888.                       } else if (strcmp(name, "if-empty") == 0) {
  889.                         unsigned long int adr = 0;
  890.                         if (inthash_readptr(NewLangList, pos2, (long int *)&adr) && *((char*)adr) != 0 ) {
  891.                           outputmode = -1;
  892.                         }
  893.                       } else if (strcmp(name, "end-if") == 0) {
  894.                         outputmode = 0;
  895.                       } else if (strcmp(name, "loadhash") == 0) {
  896.                         unsigned long int adr = 0;
  897.                         if (inthash_readptr(NewLangList, "path", (long int *)&adr)) {
  898.                           char* rpath = (char*) adr;
  899.                           //find_handle h;
  900.                           if (rpath[0]) {
  901.                             if (rpath[strlen(rpath)-1]=='/') {
  902.                               rpath[strlen(rpath)-1]='\0';      /* note: patching stored (inhash) value */
  903.                             }
  904.                           }
  905.                           {
  906.                             char* profiles = hts_getcategories(rpath, 0);
  907.                             char* categ = hts_getcategories(rpath,1 );
  908.                             inthash_write(NewLangList, "winprofile", (unsigned long int)profiles);
  909.                             inthash_write(NewLangList, "wincateg", (unsigned long int)categ);
  910.                           }
  911.                         }  
  912.                       } else if (strcmp(name, "copy") == 0) {
  913.                         if (*pos2) {
  914.                           char* pos3 = strchr(pos2, ':');
  915.                           if ( pos3 && *(pos3 + 1) ) {
  916.                             unsigned long int adr = 0;
  917.                             *pos3++ = '\0';
  918.                             if (inthash_readptr(NewLangList, pos2, (long int *)&adr)) {
  919.                               inthash_write(NewLangList, pos3, (unsigned long int)strdup((char*)adr));
  920.                               inthash_write(NewLangList, pos2, (unsigned long int)NULL);
  921.                             }
  922.                           }
  923.                         }
  924.                       } else if (strcmp(name, "set") == 0) {
  925.                         if (*pos2) {
  926.                           char* pos3 = strchr(pos2, ':');
  927.                           if ( pos3 ) {
  928.                             *pos3++ = '\0';
  929.                             inthash_write(NewLangList, pos2, (unsigned long int)strdup(pos3));
  930.                           } else {
  931.                             inthash_write(NewLangList, pos2, (unsigned long int)NULL);
  932.                           }
  933.                         }
  934.                       }
  935.                     }
  936.                     /*
  937.                     test:<if exist>
  938.                     test:<if ==0>:<if ==1>:<if == 2>..
  939.                     ztest:<if == 0 || !exist>:<if == 1>:<if == 2>..
  940.                     */
  941.                     else if ( ( p = strfield(name, "test:")) || ( p = strfield(name, "ztest:")) ) {
  942.                       unsigned long int adr = 0;
  943.                       char* pos2;
  944.                       int ztest = (name[0] == 'z');
  945.                       langstr = "";
  946.                       name += p;
  947.                       pos2 = strchr(name, ':');
  948.                       if (pos2 != NULL) {
  949.                         *pos2 = '\0';
  950.                         if (inthash_readptr(NewLangList, name, (long int *)&adr) || ztest) {
  951.                           char* newadr = (char*)adr;
  952.                           if (!newadr)
  953.                             newadr = "";
  954.                           if (*newadr || ztest) {
  955.                             int npos = 0;
  956.                             name = pos2 + 1;
  957.                             format = 4;
  958.                             if (strchr(name, ':') == NULL) {
  959.                               npos = 0;  /* first is good if only one : */
  960.                               format = 0;
  961.                             } else {
  962.                               if (sscanf(newadr, "%d", &npos) != 1) {
  963.                                 if (strfield(newadr, "on")) {
  964.                                   npos = 1;
  965.                                 } else {
  966.                                   npos = 0;   /* first one will be ok */
  967.                                   format = 0;
  968.                                 }
  969.                               }
  970.                             }
  971.                             while( *name && *name != '}' && npos >= 0) {
  972.                               int end=0;
  973.                               char* fpos = strchr(name, ':');
  974.                               int n2;
  975.                               if (fpos == NULL) {
  976.                                 fpos = name + strlen(name);
  977.                                 end=1;
  978.                               }
  979.                               n2 = (int) (fpos - name);
  980.                               if (npos == 0) {
  981.                                 langstr = name;
  982.                                 *fpos='\0';
  983.                               } else if (end) {
  984.                                 npos=0;
  985.                               }
  986.                               name += n2 + 1;
  987.                               npos--;
  988.                             }
  989.                           }
  990.                         }
  991.                       }
  992.                     }
  993.                     else if (( p = strfield(name, "listid:"))) {
  994.                       char* pos2;
  995.                       name += p;
  996.                       format = 2;
  997.                       pos2 = strchr(name, ':');
  998.                       if (pos2) {
  999.                         char dname[32];
  1000.                         int n2 = (int) (pos2 - name);
  1001.                         if (n2 > 0 && n2 < sizeof(dname) - 2) {
  1002.                           unsigned long int adr = 0;
  1003.                           dname[0] = '\0';
  1004.                           strncatbuff(dname, name, n2);
  1005.                           if (inthash_readptr(NewLangList, dname, (long int *)&adr)) {
  1006.                             int n = 0;
  1007.                             if (sscanf((char*)adr, "%d", &n) == 1) {
  1008.                               listDefault = n;
  1009.                             }
  1010.                           }
  1011.                           name += n2 + 1;
  1012.                         }
  1013.                       }
  1014.                     }
  1015.                     else if (( p = strfield(name, "checked:"))) {
  1016.                       name += p;
  1017.                       format = 3;
  1018.                     }
  1019.                     if (langstr == NULL) {
  1020.                       if (strfield2(name, "#iso")) {
  1021.                         langstr = line2;
  1022.                         langstr[0] = '\0';
  1023.                         LANG_LIST(path, langstr);
  1024.                         assertf(strlen(langstr) < sizeof(line2) - 2);
  1025.                       } else {
  1026.                         langstr = LANGSEL(name);
  1027.                         if (langstr == NULL || *langstr == '\0') {
  1028.                           unsigned long int adr = 0;
  1029.                           if (inthash_readptr(NewLangList, name, (long int *)&adr)) {
  1030.                             char* newadr = (char*)adr;
  1031.                             langstr = newadr;
  1032.                           }
  1033.                         }
  1034.                       }
  1035.                     }
  1036.                     if (langstr && outputmode != -1) {
  1037.                       switch(format) {
  1038.                       case 0:
  1039.                         {
  1040.                           char* a = langstr;
  1041.                           while(*a) {
  1042.                             if (a[0] == '\\' && isxdigit(a[1]) && isxdigit(a[2])) {
  1043.                               int n;
  1044.                               char c;
  1045.                               if (sscanf(a+1, "%x", &n) == 1) {
  1046.                                 c = (char)n;
  1047.                                 StringMemcat(output, &c, 1);
  1048.                               }
  1049.                               a += 2;
  1050.                             } else if (outputmode && a[0] == '<') {
  1051.                               StringStrcat(output, "<");
  1052.                             } else if (outputmode && a[0] == '>') {
  1053.                               StringStrcat(output, ">");
  1054.                             } else if (outputmode && a[0] == '&') {
  1055.                               StringStrcat(output, "&");
  1056.                             } else if (outputmode == 3 && a[0] == ' ') {
  1057.                               StringStrcat(output, "%20");
  1058.                             } else if (outputmode >= 2 && ((unsigned char)a[0]) < 32) {
  1059.                               char tmp[32];
  1060.                               sprintf(tmp, "%%%02x", (unsigned char)a[0]);
  1061.                               StringStrcat(output, tmp);
  1062.                             } else if (outputmode == 2 && a[0] == '%') {
  1063.                               StringStrcat(output, "%%");
  1064.                             } else if (outputmode == 3 && a[0] == '%') {
  1065.                               StringStrcat(output, "%25");
  1066.                             } else {
  1067.                               StringMemcat(output, a, 1);
  1068.                             }
  1069.                             a++;
  1070.                           }
  1071.                         }
  1072.                         break;
  1073.                       case 3:
  1074.                         if (*langstr) {
  1075.                           StringStrcat(output, "checked");
  1076.                         }
  1077.                         break;
  1078.                       default: 
  1079.                         if (*langstr) {
  1080.                           int id=1;
  1081.                           char* fstr = langstr;
  1082.                           StringClear(tmpbuff);
  1083.                           if (format == 2) {
  1084.                             StringStrcat(output, "<option value=1>");
  1085.                           } else if (format == -2) {
  1086.                             StringStrcat(output, "<option value=\"");
  1087.                           }
  1088.                           while(*fstr) {
  1089.                             switch(*fstr) {
  1090.                             case 13: break;
  1091.                             case 10:
  1092.                               if (format == 1) {
  1093.                                 StringStrcat(output, StringBuff(tmpbuff));
  1094.                                 StringStrcat(output, "<br>\r\n");
  1095.                               } else if (format == -2) {
  1096.                                 StringStrcat(output, StringBuff(tmpbuff));
  1097.                                 StringStrcat(output, "\">");
  1098.                                 StringStrcat(output, StringBuff(tmpbuff));
  1099.                                 StringStrcat(output, "</option>\r\n");
  1100.                                 StringStrcat(output, "<option value=\"");
  1101.                               } else {
  1102.                                 char tmp[32];
  1103.                                 sprintf(tmp, "%d", ++id);
  1104.                                 StringStrcat(output, StringBuff(tmpbuff));
  1105.                                 StringStrcat(output, "</option>\r\n");
  1106.                                 StringStrcat(output, "<option value=");
  1107.                                 StringStrcat(output, tmp);
  1108.                                 if (listDefault == id) {
  1109.                                   StringStrcat(output, " selected");
  1110.                                 }
  1111.                                 StringStrcat(output, ">");
  1112.                               }
  1113.                               StringClear(tmpbuff);
  1114.                               break;
  1115.                             case '<':
  1116.                               StringStrcat(tmpbuff, "<");
  1117.                               break;
  1118.                             case '>':
  1119.                               StringStrcat(tmpbuff, ">");
  1120.                               break;
  1121.                             case '&':
  1122.                               StringStrcat(tmpbuff, "&");
  1123.                               break;
  1124.                             default:
  1125.                               StringMemcat(tmpbuff, fstr, 1);
  1126.                               break;
  1127.                             }
  1128.                             fstr++;
  1129.                           }
  1130.                           if (format == 2) {
  1131.                             StringStrcat(output, StringBuff(tmpbuff));
  1132.                             StringStrcat(output, "</option>");
  1133.                           } else if (format == -2) {
  1134.                             StringStrcat(output, StringBuff(tmpbuff));
  1135.                             StringStrcat(output, "\">");
  1136.                             StringStrcat(output, StringBuff(tmpbuff));
  1137.                             StringStrcat(output, "</option>");
  1138.                           } else {
  1139.                             StringStrcat(output, StringBuff(tmpbuff));
  1140.                           }
  1141.                           StringClear(tmpbuff);
  1142.                         }
  1143.                       }
  1144.                     }
  1145.                     str = pos;
  1146.                   } else {
  1147.                     if (outputmode != -1) {
  1148.                       StringMemcat(output, str, 1);
  1149.                     }
  1150.                   }
  1151.                   str++;
  1152.                 }
  1153.                 if (!nocr && prevlen != StringLength(output)) {
  1154.                   StringStrcat(output, "\r\n");
  1155.                 }
  1156.               }
  1157. #ifdef _DEBUG
  1158.               {
  1159.                 int len = (int)strlen((char*)StringBuff(output));
  1160.                 assert(len == (int)StringLength(output));
  1161.               }
  1162. #endif
  1163.             } else if (is_text(file)) {
  1164.               StringMemcat(headers, ok_text, sizeof(ok_text) - 1);
  1165.               while(!feof(fp)) {
  1166.                 int n = fread(line, 1, sizeof(line) - 2, fp);
  1167.                 if (n > 0) {
  1168.                   StringMemcat(output, line, n);
  1169.                 }
  1170.               }
  1171.             } else {
  1172.               StringMemcat(headers, ok_img, sizeof(ok_img) - 1);
  1173.               while(!feof(fp)) {
  1174.                 int n = fread(line, 1, sizeof(line) - 2, fp);
  1175.                 if (n > 0) {
  1176.                   StringMemcat(output, line, n);
  1177.                 }
  1178.               }
  1179.             }
  1180.             fclose(fp);
  1181.           } else {
  1182.             char error_hdr[] = "HTTP/1.0 404 Not Found\r\n"
  1183.               "Server: httrack small server\r\n"
  1184.               "Content-type: text/html\r\n";
  1185.             char error[] = 
  1186.               "Page not found.\r\n";
  1187.             StringStrcat(headers, error_hdr);
  1188.             StringStrcat(output, error);
  1189.             //assert(file == NULL);
  1190.           }
  1191.         }
  1192.       } else {
  1193. #ifdef _DEBUG
  1194.         char error_hdr[] = "HTTP/1.0 500 Server Error\r\n"
  1195.           "Server: httrack small server\r\n"
  1196.           "Content-type: text/html\r\n";
  1197.         char error[] = 
  1198.           "Server error.\r\n";
  1199.         StringStrcat(headers, error_hdr);
  1200.         StringStrcat(output, error);
  1201. #endif
  1202.       }
  1203.       {
  1204.         char tmp[256];
  1205.         sprintf(tmp, "Content-length: %d\r\n", (int) StringLength(output));
  1206.         StringStrcat(headers, tmp);
  1207.       }
  1208.       StringStrcat(headers, "\r\n");
  1209.       if (
  1210.           (send(soc_c, StringBuff(headers), StringLength(headers), 0) != StringLength(headers))
  1211.           ||
  1212.           ( (meth == 1) && (send(soc_c, StringBuff(output), StringLength(output), 0) != StringLength(output)) )
  1213.         ) {
  1214. #ifdef _DEBUG
  1215.         //assert(FALSE);
  1216. #endif
  1217.       }
  1218.     } else {
  1219. #ifdef _DEBUG
  1220.       // assert(FALSE);
  1221. #endif
  1222.     }
  1223.     
  1224.     /* Shutdown (FIN) and wait until confirmed */
  1225.     {
  1226.       char c;
  1227. #ifdef _WIN32
  1228.       shutdown(soc_c, SD_SEND);
  1229. #else
  1230.       shutdown(soc_c, 1);
  1231. #endif
  1232.       /* This is necessary as IE sometimes (!) sends an additional CRLF after POST data */
  1233.       while(recv(soc_c, ((char*)&c), 1, 0) > 0);
  1234.     }
  1235.  
  1236. #if HTS_WIN
  1237.     closesocket(soc_c);
  1238. #else
  1239.     close(soc_c);
  1240. #endif
  1241.   }
  1242.  
  1243.   if (soc != INVALID_SOCKET) {
  1244. #ifdef _WIN32
  1245.     closesocket(soc);
  1246. #else
  1247.     close(soc);
  1248. #endif
  1249.   }
  1250.  
  1251.   StringFree(headers);
  1252.   StringFree(output);
  1253.   StringFree(tmpbuff);
  1254.   StringFree(tmpbuff2);
  1255.   StringFree(fspath);
  1256.  
  1257.   if (buffer)
  1258.     free(buffer);
  1259.  
  1260.   if (commandReturnMsg)
  1261.     free(commandReturnMsg);
  1262.   commandReturnMsg = NULL;
  1263.   if (commandReturnCmdl)
  1264.     free(commandReturnCmdl);
  1265.   commandReturnCmdl = NULL;
  1266.  
  1267.   /* Unlock */
  1268.   webhttrack_lock(0);
  1269.  
  1270.   return retour;
  1271. }
  1272.  
  1273.  
  1274.  
  1275. /* Language files */
  1276.  
  1277.  
  1278. int htslang_init() {
  1279.   if (NewLangList==NULL) {
  1280.     int i = 0;
  1281.     NewLangList=inthash_new(NewLangListSz);
  1282.     if (NewLangList==NULL) {
  1283.       abortLog("Error in lang.h: not enough memory");
  1284.     } else {
  1285.       inthash_value_is_malloc(NewLangList,1);
  1286.     }
  1287.   }
  1288.   return 1;
  1289. }
  1290.  
  1291. int htslang_uninit() {
  1292.   if (NewLangList!=NULL) {
  1293.     inthash_delete(&NewLangList);
  1294.   }
  1295.   return 1;
  1296. }
  1297.  
  1298. int smallserver_setkey(char* key, char* value) {
  1299.   return inthash_write(NewLangList, key, (unsigned long int)strdup(value));
  1300. }
  1301. int smallserver_setkeyint(char* key, LLint value) {
  1302.   char tmp[256];
  1303.   sprintf(tmp, LLintP, value);
  1304.   return inthash_write(NewLangList, key, (unsigned long int)strdup(tmp));
  1305. }
  1306. int smallserver_setkeyarr(char* key, int id, char* key2, char* value) {
  1307.   char tmp[256];
  1308.   sprintf(tmp, "%s%d%s", key, id, key2);
  1309.   return inthash_write(NewLangList, tmp, (unsigned long int)strdup(value));
  1310. }
  1311.  
  1312. static int htslang_load(char* limit_to, char* path) {
  1313.   char* hashname;
  1314.   //
  1315.   int selected_lang=LANG_T(path, -1);
  1316.   //
  1317.   if (!limit_to) {
  1318.     LANG_DELETE();
  1319.     NewLangStr=inthash_new(NewLangStrSz);
  1320.     NewLangStrKeys=inthash_new(NewLangStrKeysSz);
  1321.     if ((NewLangStr==NULL) || (NewLangStrKeys==NULL)) {
  1322.       abortLog("Error in lang.h: not enough memory");
  1323.     } else {
  1324.       inthash_value_is_malloc(NewLangStr,1);
  1325.       inthash_value_is_malloc(NewLangStrKeys,1);
  1326.     }
  1327.   }
  1328.  
  1329.   /* Load master file (list of keys and internal keys) */
  1330.   if (!limit_to) {
  1331.     char* mname = "lang.def";
  1332.     FILE* fp=fopen(fconcat(path, mname),"rb");
  1333.     if (fp) {
  1334.       char intkey[8192];
  1335.       char key[8192];
  1336.       while(!feof(fp)) {
  1337.         linput_cpp(fp,intkey,8000);
  1338.         linput_cpp(fp,key,8000);
  1339.         if (strnotempty(intkey) && strnotempty(key)) {
  1340.           char* test=LANGINTKEY(key);
  1341.  
  1342.           /* Increment for multiple definitions */
  1343.           if (strnotempty(test)) {
  1344.             int increment=0;
  1345.             int pos=strlen(key);
  1346.             do {
  1347.               increment++;
  1348.               sprintf(key+pos,"%d",increment);
  1349.               test=LANGINTKEY(key);
  1350.             }  while (strnotempty(test));
  1351.           }
  1352.  
  1353.           if (!strnotempty(test)) {         // Θviter doublons
  1354.             // conv_printf(key,key);
  1355.             int len;
  1356.             char* buff;
  1357.             len=strlen(intkey);
  1358.             buff=(char*)malloc(len+2);
  1359.             if (buff) {
  1360.               strcpybuff(buff,intkey);
  1361.               inthash_add(NewLangStrKeys,key,(long int)(char*)buff);
  1362.             }
  1363.           }
  1364.         } // if
  1365.       }  // while
  1366.       fclose(fp);
  1367.     } else {
  1368.       return 0;
  1369.     }
  1370.   }
  1371.   
  1372.   /* Language Name? */
  1373.   {
  1374.     char name[256];
  1375.     sprintf(name,"LANGUAGE_%d",selected_lang+1);
  1376.     hashname=LANGINTKEY(name);
  1377.   }
  1378.  
  1379.   /* Get only language name */
  1380.   if (limit_to) {
  1381.     if (hashname)
  1382.       strcpybuff(limit_to, hashname);
  1383.     else
  1384.       strcpybuff(limit_to, "???");
  1385.     return 0;
  1386.   }
  1387.  
  1388.   /* Error */
  1389.   if (!hashname)
  1390.     return 0;
  1391.  
  1392.   /* Load specific language file */
  1393.   {
  1394.     int loops;
  1395.     // 2nd loop: load undefined strings
  1396.     for(loops=0;loops<2;loops++) {
  1397.       FILE* fp;
  1398.       char lbasename[1024];
  1399.       {
  1400.         char name[256];
  1401.         sprintf(name,"LANGUAGE_%d",(loops==0)?(selected_lang+1):1);
  1402.         hashname=LANGINTKEY(name);
  1403.       }
  1404.       sprintf(lbasename, "lang/%s.txt",hashname);
  1405.       fp=fopen(fconcat(path, lbasename), "rb");
  1406.       if (fp) {
  1407.         char extkey[8192];
  1408.         char value[8192];
  1409.         while(!feof(fp)) {
  1410.           linput_cpp(fp,extkey,8000);
  1411.           linput_cpp(fp,value,8000);
  1412.           if (strnotempty(extkey) && strnotempty(value)) {
  1413.             int len;
  1414.             char* buff;
  1415.             char* intkey;
  1416.             
  1417.             intkey=LANGINTKEY(extkey);
  1418.             
  1419.             if (strnotempty(intkey)) {
  1420.               
  1421.               /* Increment for multiple definitions */
  1422.               {
  1423.                 char* test=LANGSEL(intkey);
  1424.                 if (strnotempty(test)) {
  1425.                   if (loops == 0) {
  1426.                     int increment=0;
  1427.                     int pos=strlen(extkey);
  1428.                     do {
  1429.                       increment++;
  1430.                       sprintf(extkey+pos,"%d",increment);
  1431.                       intkey=LANGINTKEY(extkey);
  1432.                       if (strnotempty(intkey))
  1433.                         test=LANGSEL(intkey);
  1434.                       else
  1435.                         test="";
  1436.                     }  while (strnotempty(test));
  1437.                   } else
  1438.                     intkey="";
  1439.                 } else {
  1440.                   if (loops > 0) {
  1441.                     //err_msg += intkey;
  1442.                     //err_msg += " ";
  1443.                   }
  1444.                 }
  1445.               }
  1446.               
  1447.               /* Add key */
  1448.               if (strnotempty(intkey)) {
  1449.                 len=strlen(value);
  1450.                 buff=(char*)malloc(len+2);
  1451.                 if (buff) {
  1452.                   conv_printf(value,buff);
  1453.                   inthash_add(NewLangStr,intkey,(long int)(char*)buff);
  1454.                 }
  1455.               }
  1456.               
  1457.             }
  1458.           } // if
  1459.         }  // while
  1460.         fclose(fp);
  1461.       } else {
  1462.         return 0;
  1463.       }
  1464.     }
  1465.   }
  1466.  
  1467.   // Control limit_to
  1468.   if (limit_to)
  1469.     limit_to[0]='\0';
  1470.  
  1471.   return 1;
  1472. }
  1473.  
  1474. /* NOTE : also contains the "webhttrack" hack */
  1475. static void conv_printf(char* from,char* to) {
  1476.   int i=0,j=0,len;
  1477.   len=strlen(from);
  1478.   while(i<len) {
  1479.     switch(from[i]) {
  1480.     case '\\': 
  1481.       i++;
  1482.       switch(from[i]) {
  1483.       case 'a': to[j]='\a'; break;
  1484.       case 'b': to[j]='\b'; break;
  1485.       case 'f': to[j]='\f'; break;
  1486.       case 'n': to[j]='\n'; break;
  1487.       case 'r': to[j]='\r'; break;
  1488.       case 't': to[j]='\t'; break;
  1489.       case 'v': to[j]='\v'; break;
  1490.       case '\'': to[j]='\''; break;
  1491.       case '\"': to[j]='\"'; break;
  1492.       case '\\': to[j]='\\'; break;
  1493.       case '?': to[j]='\?'; break;
  1494.       default: to[j]=from[i]; break;
  1495.       }
  1496.       break;
  1497.       default: 
  1498.         to[j]=from[i]; 
  1499.         break;
  1500.     }
  1501.     i++;
  1502.     j++;
  1503.   }
  1504.   to[j++]='\0';
  1505.   /* Dirty hack */
  1506.   {
  1507.     char * a = to;
  1508.     while((a = strstr(a, "WinHTTrack"))) {
  1509.       a[0] = 'W';
  1510.       a[1] = 'e';
  1511.       a[2] = 'b';
  1512.       a++;
  1513.     }
  1514.   }
  1515. }
  1516.  
  1517. static void LANG_DELETE() {
  1518.   inthash_delete(&NewLangStr);
  1519.   inthash_delete(&NewLangStrKeys);
  1520. }
  1521.  
  1522. // sΘlection de la langue
  1523. static void LANG_INIT(char* path) {
  1524.   //CWinApp* pApp = AfxGetApp();
  1525.   //if (pApp) {
  1526.     int test = 0; /* pApp->GetProfileInt("Language","IntId",0); */
  1527.     LANG_T(path, 0 /*pApp->GetProfileInt("Language","IntId",0)*/ );
  1528.   //}
  1529. }
  1530.  
  1531. static int LANG_T(char* path, int l) {
  1532.   if (l>=0) {
  1533.     QLANG_T(l);
  1534.     htslang_load(NULL, path);
  1535.   }
  1536.   return QLANG_T(-1);  // 0=default (english)
  1537. }
  1538.  
  1539. static int LANG_SEARCH(char* path, char* iso) {
  1540.   char lang_str[1024];
  1541.   int i = 0;
  1542.   int curr_lng=LANG_T(path, -1);
  1543.   int found = 0;
  1544.   unsigned long int adr = 0;
  1545.   do {
  1546.     QLANG_T(i);
  1547.     strcpybuff(lang_str,"LANGUAGE_ISO");
  1548.     htslang_load(lang_str, path);
  1549.     if (strfield(iso, lang_str)) {
  1550.       found = i;
  1551.     }
  1552.     i++;
  1553.   } while(strlen(lang_str) > 0);
  1554.   QLANG_T(curr_lng);
  1555.   return found;
  1556. }
  1557.  
  1558. static int LANG_LIST(char* path, char* buffer) {
  1559.   char lang_str[1024];
  1560.   int i = 0;
  1561.   int curr_lng=LANG_T(path, -1);
  1562.   int found = 0;
  1563.   buffer[0] = '\0';
  1564.   do {
  1565.     QLANG_T(i);
  1566.     strcpybuff(lang_str, "LANGUAGE_NAME");
  1567.     htslang_load(lang_str, path);
  1568.     if (strlen(lang_str) > 0) {
  1569.       if (buffer[0])
  1570.         strcatbuff(buffer, "\n");
  1571.       strcatbuff(buffer, lang_str);
  1572.     }
  1573.     i++;
  1574.   } while(strlen(lang_str) > 0);
  1575.   QLANG_T(curr_lng);
  1576.   return i;
  1577. }
  1578.  
  1579. static int QLANG_T(int l) {
  1580.   static int lng=0;
  1581.   if (l>=0) {
  1582.     lng=l;
  1583.   }
  1584.   return lng;  // 0=default (english)
  1585. }
  1586.  
  1587. static char* LANGSEL(char* name) {
  1588.   unsigned long int adr = 0;
  1589.   if (NewLangStr)
  1590.   if (!inthash_read(NewLangStr,name,(long int *)&adr))
  1591.     adr=0;
  1592.   if (adr) {
  1593.     return (char*)adr;
  1594.   }
  1595.   return "";
  1596. }
  1597.  
  1598. static char* LANGINTKEY(char* name) {
  1599.   unsigned long int adr=0;
  1600.   if (NewLangStrKeys)
  1601.   if (!inthash_read(NewLangStrKeys,name,(long int *)&adr))
  1602.     adr=0;
  1603.   if (adr) {
  1604.     return (char*)adr;
  1605.   }
  1606.   return "";
  1607. }
  1608.  
  1609.  
  1610.  
  1611.  
  1612. /* *** Various functions *** */
  1613.  
  1614.  
  1615.  
  1616. static int check_readinput_t(T_SOC soc, int timeout) {
  1617.   if (soc != INVALID_SOCKET) {
  1618.     fd_set fds;           // poll structures
  1619.     struct timeval tv;          // structure for select
  1620.     FD_ZERO(&fds);
  1621.     FD_SET(soc,&fds);           
  1622.     tv.tv_sec=timeout;
  1623.     tv.tv_usec=0;
  1624.     select(soc + 1,&fds,NULL,NULL,&tv);
  1625.     if (FD_ISSET(soc,&fds))
  1626.       return 1;
  1627.     else
  1628.       return 0;
  1629.   } else
  1630.     return 0;
  1631. }
  1632.  
  1633. static int recv_bl(T_SOC soc, void* buffer, size_t len, int timeout) {
  1634.   if (check_readinput_t(soc, timeout)) {
  1635.     int n = 1;
  1636.     size_t size = len;
  1637.     size_t offs = 0;
  1638.     while(n > 0 && size > 0) {
  1639.       n = recv(soc, ((char*)buffer) + offs, (int) size, 0);
  1640.       if (n > 0) {
  1641.         offs += n;
  1642.         size -= n;
  1643.       }
  1644.     }
  1645.     return (int)offs;
  1646.   }
  1647.   return -1;
  1648. }
  1649.  
  1650. static int linputsoc(T_SOC soc, char* s, int max) {
  1651.   int c;
  1652.   int j=0;
  1653.   do {
  1654.     unsigned char ch;
  1655.     if (recv(soc, &ch, 1, 0) == 1) {
  1656.       c = ch;
  1657.     } else {
  1658.       c = EOF;
  1659.     }
  1660.     if (c!=EOF) {
  1661.       switch(c) {
  1662.         case 13: break;  // sauter CR
  1663.         case 10: c=-1; break;
  1664.         case 9: case 12: break;  // sauter ces caractΦres
  1665.         default: s[j++]=(char) c; break;
  1666.       }
  1667.     }
  1668.   }  while((c!=-1) && (c!=EOF) && (j<(max-1)));
  1669.   s[j]='\0';
  1670.   return j;
  1671. }
  1672.  
  1673. // check if data is available
  1674. static int check_readinput(htsblk* r) {
  1675.   if (r->soc != INVALID_SOCKET) {
  1676.     fd_set fds;           // poll structures
  1677.     struct timeval tv;          // structure for select
  1678.     FD_ZERO(&fds);
  1679.     FD_SET(r->soc,&fds);           
  1680.     tv.tv_sec=0;
  1681.     tv.tv_usec=0;
  1682.     select(r->soc + 1,&fds,NULL,NULL,&tv);
  1683.     if (FD_ISSET(r->soc,&fds))
  1684.       return 1;
  1685.     else
  1686.       return 0;
  1687.   } else
  1688.     return 0;
  1689. }
  1690.  
  1691. static int linputsoc_t(T_SOC soc, char* s, int max, int timeout) {
  1692.   if (check_readinput_t(soc, timeout)) {
  1693.     return linputsoc(soc, s, max);
  1694.   }
  1695.   return -1;
  1696. }
  1697.  
  1698. /*int strfield(const char* f,const char* s) {
  1699.   int r=0;
  1700.   while (streql(*f,*s) && ((*f)!=0) && ((*s)!=0)) { f++; s++; r++; }
  1701.   if (*s==0)
  1702.     return r;
  1703.   else
  1704.     return 0;
  1705. }*/
  1706.  
  1707. /* same, except + */
  1708.  
  1709.